module EvaluationFunctions
  
  #FEATURE IDEAS:
  #normalized points
  #chance they have atleast 1 valid ( chance they draw ) Thats: for hand size h pool size p its (p-1)C(h-1) + (p-2)C(h-1)....(p-h)C(h-1) / pCh
  #OR (maybe) total - (non_val C h_size) / total. Total minus number of hands without valids (equals number with valids) divided by total hands
  
  def self.init(l)
    puts "initializing n choose k"
    $logger.debug "initializing n choose k"
    @@lookup_table = initialize_n_choose_k l
  end
  
  def initial_probability(hand_size, pool_size)
    num_included = @@lookup_table[pool_size - 1][hand_size - 1]
    total_hands = @@lookup_table[pool_size][hand_size]
    frac = (num_included.to_f/total_hands.to_f).round(4)
    puts "prob hash size #{@prob_hash.size} and prob hash prob hash stickies #{@prob_hash.num_sticky}"
    puts "hand size is #{hand_size} part of #{num_included} hands, unstuck size is #{pool_size} total hands #{total_hands} frac is #{frac}"
    $logger.debug "initial probabity is #{frac}"
    frac
  end
  
  def get_best_move
    player = current_player
    valids = (player.is_a? HumanPlayer) ? valid_generator(player.hand.dominoes, @board) : valid_generator(@pool.dominoes, @board)
    
    puts "\n\n**going to calculate best move and show output!"
    puts "valids are #{valids}"
    
    results = []
    
    valids.each do |k, v|
      v.each do |l|
        
        puts "\nlooking at playing #{k} on #{l}"
        
        dg = self.dup_state
        domino = k.dup
        dominee = l.dup
        
        p = Features::ScoringPoints::WEIGHT * Features::ScoringPoints.evaluate_game(dg, domino, dominee)
        results << {:points => p, :domino => k, :dominee => l}
        
        puts "#{dg.board}"
        
      end
    end
    
    max_play = results.max_by{|x| x[:points]}
    max_play
  end
  
  def most_points
    raise NotImplementedError
  end
  
  def init_prob_hash
    p = initial_probability(@opp.hand.size, @pool.size)
    @prob_hash.init p, @pool.dominoes
  end
  
  def self.initialize_n_choose_k(limit)
    b = (1..limit+1).inject(0){|memo, i|  memo + i}
    
    lookup_table = []
    #initialize
    (0..b).each {|n| lookup_table[n] = [1]}
    (1..b).each {|k| lookup_table[0][k] = 0}
    
    (1..b).each do |n|
      (1..b).each do |k|
        lookup_table[n][k] = lookup_table[n-1][k-1] + lookup_table[n-1][k]
      end
    end
    lookup_table
  end
  
  def remove_valids_from_prob_hash
    #valids should already be defined but we will get them again for now, possible optimization later
    vals = valid_generator(@pool.dominoes, @board)
    vals.keys.each { |val| @prob_hash[val.head, val.tail] = 0}
  end

end